#include "swpentitygraphicitem.h"

#include "../../documents/data/graphicdata.h"
#include "../../undo/basicitemcommands.h"
#include "../../utils/undomanager.h"
#include "graphicitemcommon.h"
#include "swpentitygraphicitemcontent.h"

#include <QtGui/QGraphicsScene>

using namespace core;
using namespace swp;

SwpEntityGraphicItem::SwpEntityGraphicItem(const QString& entityName,
    const QString& entityType,
    QGraphicsItem* parent) :
        AbstractPolygonGraphicItem(parent),
        m_entityName(entityName),
        m_entityNameProp()
{
    m_entityNameProp.Name = "class";
    m_entityNameProp.Text = QObject::tr("Class name");
    m_entityNameProp.setValue(QVariant(m_entityName));

    QPolygonF polygon;
    polygon << QPointF(0.0, 0.0) << QPointF(100.0, 0.0) <<
        QPointF(100.0, 62.0) << QPointF(0.0, 62.0) << QPointF(0.0, 0.0);

    setPolygonF(polygon);

    setFlags(flags() | QGraphicsItem::ItemIsMovable |
        QGraphicsItem::ItemIsSelectable);

    setContent(new SwpEntityGraphicItemContent(entityType,
        entityName, this));

    setAntialiasing(false);
}

SwpEntityGraphicItem::~SwpEntityGraphicItem()
{

}

QString SwpEntityGraphicItem::entityName() const
{
    return m_entityName;
}

bool SwpEntityGraphicItem::supportsConnection(
    const ConnectionData& connection) const
{
    bool ret = false;

    if (connection.ConnectionId != CONNECTION_NOT_VALID
        && connection.From != this && !containsSameConnection(connection))
    {
        int fromType = connection.From != 0 ? connection.From->type() :
            INVALID_TYPE;
        int toType = connection.To != 0 ? connection.To->type() :
            INVALID_TYPE;

        if (connection.ConnectionId == CONNECTION_AGGREGATION)
        {
            ret = true;
        }
        else if (connection.ConnectionId == CONNECTION_ASSOCIATION)
        {
            ret = true;
        }
        else if (connection.ConnectionId == CONNECTION_COMPOSITION)
        {
            ret = true;
        }
        else if (connection.ConnectionId == CONNECTION_DEPENDENCY)
        {
            ret = true;
        }
        else if (connection.ConnectionId == CONNECTION_GENERALIZATION &&
            fromType == toType)
        {
            ret = true;
        }
        else if (connection.ConnectionId == CONNECTION_REALIZATION)
        {
            ret = true;
        }
    }

    return ret;
}

QList<Property> SwpEntityGraphicItem::properties() const
{
    QList<Property> ret;

    ret.append(m_entityNameProp);

    return ret;
}

QVariant SwpEntityGraphicItem::propertyValue(
    const QString& propertyName) const
{
    QVariant ret;

    if (propertyName == "class")
    {
        ret = m_entityNameProp.value();
    }

    return ret;
}

void SwpEntityGraphicItem::propertyChanged(const QString& property,
    const QVariant& newValue, bool silent)
{
    if (property == m_entityNameProp.Name &&
        m_entityNameProp.value() != newValue)
    {
        if (!silent)
        {
            PropertyChangeCommand* command = new PropertyChangeCommand(
                this, m_entityNameProp, newValue);

            UndoManager::getInstance()->push(
                dynamic_cast<IDocumentData*>(scene()), command);
        }

        m_entityNameProp.setValue(newValue);
        m_entityName = newValue.toString();

        SwpEntityGraphicItemContent* _content =
            dynamic_cast<SwpEntityGraphicItemContent*>(content());

        Q_ASSERT(_content != 0); // content mismatch

        _content->setEntityName(m_entityName);

        if (silent && isSelected()) {
            setSelected(false);
            setSelected(true);
        }

        if (silent)
        {
            GraphicData* data = dynamic_cast<GraphicData*>(m_documentData);

            Q_ASSERT(data != 0); // shouldn't be null

            data->emitDataChanged();
        }
    }
}

QVariantList SwpEntityGraphicItem::optionList(
    const QString& propertyName) const
{
    QVariantList ret;

    return ret;
}

QVariantList SwpEntityGraphicItem::autocomplete(
    const QString& propertyName) const
{
    QVariantList ret;

    return ret;
}

QList<QPointF> SwpEntityGraphicItem::scalePoints() const
{
    QList<QPointF> ret;

    ret << QPointF(100.0, 0.0) << QPointF(100.0, 125.0)
        << QPointF(0.0, 62.0) << QPointF(200.0, 62.0);

    return ret;
}

QList<QPointF> SwpEntityGraphicItem::connectPoints() const
{
    QList<QPointF> ret;

    ret << QPointF(0.0, 0.0) << QPointF(100.0, 0.0) <<
           QPointF(200.0, 0.0) << QPointF(200.0, 62.0) <<
           QPointF(200.0, 125.0) << QPointF(100.0, 125.0) <<
           QPointF(0.0, 125.0) << QPointF(0.0, 62.0);

    return ret;
}

QList<QPointF> SwpEntityGraphicItem::selfConnectAnchorPoints() const
{
    QList<QPointF> ret;

    ret << QPointF(-20.0, -20.0) << QPointF(100.0, -20.0) <<
           QPointF(220.0, -20.0) << QPointF(220.0, 62.0) <<
           QPointF(220.0, 145.0) << QPointF(100.0, 145.0) <<
           QPointF(-20.0, 145.0) << QPointF(-20.0, 62.0);

    return ret;
}

bool SwpEntityGraphicItem::containsSameConnection(
    const ConnectionData& connection) const
{
    bool ret = false;

    const QList<ConnectionData> _connections = connections();

    foreach (const ConnectionData& _connection, _connections)
    {
        if (ConnectionComparator::compare(connection, _connection,
            ConnectionComparator::WithoutConnectionType |
            ConnectionComparator::WithoutConnector |
            ConnectionComparator::WithoutDirection))
        {
            ret = true;
            break;
        }
    }

    return ret;
}
